﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using BattleCore;
using BattleCore.Events;
using PsyModules;

namespace Battle
{
    public class PubControl
    {
        private string FlagOwner = "~nobody";

        // Custom chat module
        private ShortChat msg = new ShortChat();
        // bounty to start pub players at
        private ushort _StartBounty = 100;

        private MeterMaid m_Parking = new MeterMaid();
        PrizeControl m_Prizes = new PrizeControl();

        ScoreBoard BZ_Bux_Lvz = new ScoreBoard();
        FadeDisplay FadeAward = new FadeDisplay();
        PublicStore BZMart = new PublicStore();
        WeighedRandom ran_Green = new WeighedRandom();
        WeighedRandom ran_Kill = new WeighedRandom();

        // 2 main regions to public map
        private ushort[,] PublicCoords = new ushort[,] { { 225, 328, 799, 724 }, { 347, 724, 677, 846 } };

        private List<PublicPlayer> _PublicList = new List<PublicPlayer>();

        // Load all initial settings for pub
        public void LoadPubSettings()
        {
            ran_Green.Weight_Range = new List<int[]>(8);
            ran_Green.Weight_Range.Add(new int[] { 5, 50 });
            ran_Green.Weight_Range.Add(new int[] { 8, 25 });
            ran_Green.Weight_Range.Add(new int[] { 10, 5 });
            ran_Green.Weight_Range.Add(new int[] { 20, 4 });
            ran_Green.Weight_Range.Add(new int[] { 30, 3 });
            ran_Green.Weight_Range.Add(new int[] { 40, 2 });
            ran_Green.Weight_Range.Add(new int[] { 50, 1 });
            ran_Green.CreateRandomArray();

            ran_Kill.Weight_Range = new List<int[]>(4);
            ran_Kill.Weight_Range.Add(new int[] { 200, 50 });
            ran_Kill.Weight_Range.Add(new int[] { 250, 25 });
            ran_Kill.Weight_Range.Add(new int[] { 300, 5 });
            ran_Kill.Weight_Range.Add(new int[] { 350, 2 });
            ran_Kill.CreateRandomArray();

            m_Parking.SetParkingToys();
            // setting all the lvz ids
            BZ_Bux_Lvz.LvzBaseIDs = new int[] { 0, 10, 20, 30, 40, 50, 60, 70, 80 };
            FadeAward.LvzBaseIDs = new int[] { 100, 110, 120, 130, 140, 150, 160, 170, 180 };
            BZMart.LoadSettings();
        }

        // Make a random warp for players into pub
        private ChatEvent PublicWarpToCommand(string PlayerName)
        {
            // 1 in 6 chance to start in bottom area
            Random ran = new Random();
            int a = ran.Next(0, 6);
            int b;
            if (a != 0) b = 0;
            else b = 1;
            // return warp message back
            int x = ran.Next(PublicCoords[b, 0], PublicCoords[b, 2]);
            int y = ran.Next(PublicCoords[b, 1], PublicCoords[b, 3]);
            // Set up with command
            return (msg.pm(PlayerName,"*warpto " + x + " " + y));
        }

        public void AssignFlagOwner(string FlagOwner)
        {
            this.FlagOwner = FlagOwner;
        }
        public void ReleaseFlagCheck(string FlagOwner)
        {
            if (this.FlagOwner == FlagOwner)
                this.FlagOwner = "~nobody";
        }
        // Store info and award points
        public Queue<EventArgs> GotGreen(string PlayerName)
        {
            Queue<EventArgs> reply = new Queue<EventArgs>();

            PublicPlayer player = GetPlayer(PlayerName);
            // Go into player profile and increase greens
            player.GotGreen();
            // Get award amount for green
            double AwardAmount = ran_Green.ReturnRandomValue() * .01;
            // return info
            reply = UpdateBatBux(player, true,AwardAmount);

            return reply;
        }
        // Store info and award points
        public Queue<EventArgs> DeathEvent(PlayerDeathEvent p)
        {
            Queue<EventArgs> reply = new Queue<EventArgs>();

            PublicPlayer Killer = GetPlayer(p.KillerName);
            PublicPlayer Killed = GetPlayer(p.KilledName);

            if (p.FlagsCarried > 0)
                FlagOwner = Killer.PlayerName;

            double AwardAmount = ran_Kill.ReturnRandomValue() * .01;
            reply = UpdateBatBux(Killer, true, AwardAmount);

            Killer.KilledPlayer();
            Killed.Died();

            return reply;
        }
        // Store Damage info
        public void DamageEvent(WatchDamageEvent w)
        {
            PublicPlayer Dealer = GetPlayer(w.AttackerName);
            PublicPlayer DealtTo = GetPlayer(w.PlayerName);

            // If player damaged himself
            if (Dealer == DealtTo)
                Dealer.SelfDamage(w.Damage);
            else
            {
                Dealer.DeltDamage(w.Damage);
                DealtTo.TookDamage(w.Damage);
            }
        }
        // ------------------------------\\
        //  PlayerPosition / Regions      |
        // ------------------------------//
        // Incoming player position events get handled here
        public Queue<EventArgs> PositionEvent(StatusControl.MainPlayer m_Player, RegionType RegType, PlayerPositionEvent p)
        {
            Queue<EventArgs> reply = new Queue<EventArgs>();

            if (RegType == RegionType.StartBox)
            {
                // If player comes from spec, change player status to pub
                // Also adds player to Public master list
                if (m_Player.PlayerStatus == Status.InSpec)
                {
                    PublicPlayer player = GetPlayer(p.PlayerName);
                    if (player.PlayerName == null)
                    {
                        
                        PublicPlayer newP = new PublicPlayer();
                        newP.PlayerName = p.PlayerName;
                        _PublicList.Add(newP);
                    }
                    m_Player.PlayerStatus = Status.InPublic;
                }

                // Prep player with prizes and warp him into pub area
                if (m_Player.PlayerStatus == Status.InPublic)
                {
                    reply.Enqueue(PublicWarpToCommand(p.PlayerName));

                    if (p.Bounty == 0)
                    {
                        PublicPlayer player = GetPlayer(p.PlayerName);
                        int amount2prize = 100;
                        if (player.Greens > 100)
                            amount2prize = player.Greens;

                        m_Prizes.LoadPrizeState(p.PlayerName, player.Prizes, reply);
                        reply.Enqueue(msg.pm(p.PlayerName, "*prize " + (amount2prize - player.Prizes.PrizeAmount)));
                    }
                }
                // Send player to parking area and load player state
                else if (m_Player.PlayerStatus == Status.Parking)
                {
                    reply = (m_Parking.ParkingEntrance(p));
                }
            }
            // Send player to parking area and load player state
            else if (RegType == RegionType.ParkingEntrance)
            {
                m_Player.PlayerStatus = Status.Parking;
                reply = (m_Parking.ParkingEntrance(p));
            }
            // Exiting parking
            else if (RegType == RegionType.ParkingExit)
            {
                m_Player.PlayerStatus = Status.InPublic;
                reply = (m_Parking.ParkinExit(p));
            }
            else if (RegType == RegionType.InStore)
                reply = BZMart.InsideStore(p);
            else if (RegType == RegionType.StoreExitLeft || RegType == RegionType.StoreExitRight)
                reply = BZMart.StoreExit(p);

            // Update warpstamp
            if (RegType == RegionType.ParkingEntrance || RegType == RegionType.StartBox || RegType == RegionType.ParkingExit)
                m_Player.WarpStamp = DateTime.Now;

            return reply;
        }
        // ------------------------------\\
        //  Score Related                 |
        // ------------------------------//
        public Queue<EventArgs> UpdateBatBux(PublicPlayer Player, bool Add, double Amount)
        {
            // Hold the old score
            int OldScore = (int)(Player.BZBux * 100);

            // Check to see if there is any multiplier
            if (FlagOwner == Player.PlayerName && Add)
                Amount *= 2;

            // Do we add or subtract amount
            if (Add)
                Player.BZBux += Amount;
            else
                Player.BZBux -= Amount;

            // Hold new score
            int NewScore = (int)(Player.BZBux * 100);

            // Create the event q
            Queue<EventArgs> reply = new Queue<EventArgs>();
            // Load new gfx for player display on bz bux
            reply.Enqueue(msg.pm(Player.PlayerName, BZ_Bux_Lvz.UpdateScoreCommand(OldScore, NewScore)));
            // Create a new fade gfx with reward
            reply.Enqueue(msg.pm(Player.PlayerName, FadeAward.FadeScoreCommand(Add, (int)(Amount * 100))));
            // send it back
            return reply;
        }

        // ------------------------------\\
        //  Misc                          |
        // ------------------------------//
        // Retrieve player info from list
        public PublicPlayer GetPlayer(string PlayerName)
        {
            PublicPlayer player = new PublicPlayer();

            _PublicList.ForEach(delegate(PublicPlayer p)
            {
                if (p.PlayerName == PlayerName)
                    player = p;
            });
            return player;
        }

        // ------------------------------\\
        //  Chat Commands                 |
        // ------------------------------//
        public Queue<EventArgs> PubChatCommands(ChatEvent c)
        {
            Queue<EventArgs> reply = new Queue<EventArgs>();
            PublicPlayer player = GetPlayer(c.PlayerName);

            if (c.Message.StartsWith("!stats"))
                MyStats(c, reply);
            else if (c.Message.StartsWith("!inv"))
                reply = BZMart.GetInventory(c.PlayerName);
            else if (c.Message.StartsWith("!buy"))
            {
                if (BZMart.IsInStore(c.PlayerName))
                {
                    if (c.Message.Contains(" "))
                        reply = BZMart.MakePurchase(player, c.Message.Split(' ')[1]);
                }
                else
                    reply.Enqueue(msg.pm(c.PlayerName,"Purchases may only be done inside of store, a delivery service will be added in the future.**(Delivery charges will apply)**"));
            }

            return reply;
        }
        public void MyStats(ChatEvent c, Queue<EventArgs> reply)
        {
            bool found = false;

            _PublicList.ForEach(delegate(PublicPlayer p)
            {
                if (p.PlayerName == c.PlayerName)
                {
                    found = true;
                    reply.Enqueue(msg.pm(c.PlayerName, "-----------------------<[ " + c.PlayerName + "'s Stats ]-----------------------<"));
                    reply.Enqueue(msg.pm(c.PlayerName, "      Points:     Total[" + p.Points.ToString().PadLeft(5, ' ') + " ] BZ Bux $[" + String.Format("{0:0.00}", p.BZBux).PadLeft(5, ' ') + "]"));
                    reply.Enqueue(msg.pm(c.PlayerName, "Total Deaths:     Kills[" + p.Kills.ToString().PadLeft(5, ' ') + " ]   Losses[" + p.Losses.ToString().PadLeft(5, ' ') + "]"));
                    reply.Enqueue(msg.pm(c.PlayerName, "Total Damage:      Delt[" + p.DamageDelt.ToString().PadLeft(5, ' ') + " ] Received[" + p.DamageTaken.ToString().PadLeft(5, ' ') + "]   Self[" + p.SelfDamages.ToString().PadLeft(5, ' ') + " ]"));
                    reply.Enqueue(msg.pm(c.PlayerName, "      Greens:     Total[" + p.Greens.ToString().PadLeft(5, ' ') + " ] "));
                }
            });

            if (!found)
                reply.Enqueue(msg.pm(c.PlayerName, "You do not appear to be in the Public List."));

            //return reply;
        }
    }
}
//option to buy more slots
//decoys-wall-rocket-burst-portal-rep-thor-wall
//        5  / 6 / 7 /   8 / 9 / 10 /11 / 12
